package main

import (
	"fmt"
	"sync"
)

func main() {
	var wg sync.WaitGroup
	wg.Add(2) // 登记 2 个任务

	go func() {
		defer wg.Done()
		fmt.Println("job 1")
	}()

	go func() {
		defer wg.Done()
		fmt.Println("job 2")
	}()

	wg.Wait() // 阻塞直到计数器变 0
	fmt.Println("all done")
}
// 对于一个可寻址的 sync.WaitGroup 值 wg：
// 我们可以使用方法调用 wg.Add(delta) 来改变值 wg 维护的计数。
// 方法调用 wg.Done() 和 wg.Add(-1) 是完全等价的。
// 如果一个 wg.Add(delta) 或者 wg.Done() 调用将 wg 维护的计数更改成一个负数，一个恐慌将产生。
// 当一个协程调用了 wg.Wait() 时，
// 如果此时 wg 维护的计数为零，则此 wg.Wait() 此操作为一个空操作（noop）；
// 否则（计数为一个正整数），此协程将进入阻塞状态。当以后其它某个协程将此计数更改至 0 时（一般通过调用 wg.Done()），此协程将重新进入运行状态（即 wg.Wait() 将返回）。